package core.sim;

import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.util.*;

import stats.*;
import core.genetic.*;

import static utility.Utils.sqr;

public class FunctionOptimization implements SingleSimulation {

	@Override
	public int getInfluencesCount() {
		return 0;
	}

	@Override
	public int getInputCounts() {
		return 4;
	}

	@Override
	public int getOutputCounts() {
		return 1;
	}

	@Override
	public int getSurroungingsCount() {
		return 0;
	}

	@Override
	public double[] playSimulation(Individual[] individuals) {
		int i = 0;
		int n = individuals.length;
		
		double[] res = new double[n];
		for (Individual ind : individuals) {
			double x = ind.getGene(0);//+1)*5;
			double y = ind.getGene(1);//+1)*5;								
//			res[i] = - ((x-y-0.2)*(x-y-0.2) + (x+y-0.6)*(x+y-0.6));
			double z = ind.getGene(2);
			double t = ind.getGene(3);
			double u = ind.getGene(4);
//			//  x = 0.4 , y = 0.2 , z = 0.1 , t = 0.6 , u = 0.1
			res[i] = - fja(x,y,z,t,u); //Math.log(3.720075976020836E-44+Math.abs(f(x,y,z,t,u)));//Math.sqrt(Math.sqrt(sqr(x-y-0.2) + sqr(x+y-0.6)+ sqr(x-z-0.3) + sqr(x-t+0.2)+ sqr(u+x-0.5))) ;
			
			//res[i] = - Math.exp(-3*t*Math.cos(10*t));
			Statistics.addTeamResult(res[i]);
			i++;
		}
//		System.out.println("\t\t" + Arrays.toString(res) + "\t\t" + Arrays.toString(individuals));
//		System.out.flush();
		return res;
	}
	
	public static double fja(double... xx) 
	{
		double res = 0;
		for(double x : xx)
		{
			x*=20;
			res+= Math.abs(x) - 10 * Math.cos(Math.sqrt(10*Math.abs(x)));
		}
		return res;
	}

	public static double f(double x, double y, double z, double t, double u) {
		return p(x, new double[]{-0.962, -0.703, -0.506, -0.372, -0.114, 0.175, 0.344, 0.550, 0.886, 0.999})
			+ p(y, new double[]{-0.903,-0.787,-0.583,-0.395, -0.187, 0.124, 0.348, 0.501, 0.765, 0.902})
			+ p(z, new double[]{-0.928,-0.835, -0.633, -0.418,-0.205, -0.079, 0.278, 0.495, 0.653, 0.885})
			+ p(t, new double[]{-.966, -0.809,-0.645, 0.414,-0.299, 0.038, 0.284, 0.479, 0.664, 0.894})
			+ p(u, new double[]{-.909, -0.749, -0.569,-0.355,-0.162, 0.187, 0.351, -0.527, 0.705, 0.978})
//			+ p(x, new double[]{0.943, -0.113, -0.195, 0.023}) * p(y, new double[]{-0.811, 0.918, 0.079, 0.211}) * p(z, new double[]{-0.600, 0.341, -0.323, -0.465})
//			+ p(t, new double[]{-0.410, -0.063, 0.998, -0.899, 0.280, -0.259}) * p(u, new double[]{0.644, 0.017, -0.820, 0.435, -0.481, 0.460})
			;
	}
	
	private static double p(double x, double[] zeros) {
		double res = 1;
		for(double zero : zeros)
			res*=(x-zero);
		return res;
	}
	
	@Override
	public void drawSimulation(Population pop, double[] values) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void drawMovie(Graphics2D g2, Point2D dim) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void executeForMovie(Individual[] individuals) {
		// TODO Auto-generated method stub
		
	}

}
